/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.nb.jobs.properties;

import coalescent.nb.jobs.properties.editors.AnPropertyEditor;
import coalescent.nb.jobs.properties.editors.PhylogenyAlgorithmPropertyEditor;
import coalescent.nb.jobs.properties.editors.PropertyEditors;
import coalescent.phylogeny.PhylogenyAlgo;
import commons.nb.jobs.properties.BuilderProperty;
import commons.nb.jobs.properties.Property;
import commons.nb.jobs.properties.PropertySets;
import commons.nb.jobs.properties.Propertys;
import commons.nb.jobs.properties.editors.ValidatingInplaceEditor;
import commons.nb.jobs.properties.editors.ValidatingStringInplaceEditor;
import org.netbeans.validation.api.Validator;
import org.netbeans.validation.api.builtin.Validators;

/**
 * @author Susanta Tewari
 * @version 1.0.0
 * @history Created on Nov 23, 2011
 * @since 1.0.0
 */
public class Propertys_Coa {

    /**
     * Private constructor to prevent instantiation.
     */
    private Propertys_Coa() {}

    /**
     * Properties:
     * <ul>
     *     <li>{@code prefix.implCode = esf-multi|exact-recursion-multi}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<String> KC64_LHood_Algo(String prefix) {

        final Property<String> propImpl = Propertys.ofString();

        propImpl.setName("kc64-lhood-algo");
        propImpl.setDisplayName("KC64 LHood Algo");
        propImpl.setShortDescription("likelihood algorithm for model KC64");
        propImpl.setPropertySet(PropertySets.ALGOS);


        // property editor
        propImpl.setPropEditorClass(PropertyEditors.KC64LHoodAlgoPE.class);


        // key & value
        propImpl.setKey(prefix + ".implCode");
        propImpl.setValue("esf-multi");

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *     <li>{@code prefix.theta = a double value}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<Double> of_Theta(String prefix) {

        final Property<Double> propImpl = Propertys.ofDouble();


        // descriptions
        propImpl.setName("theta");
        propImpl.setDisplayName("theta");
        propImpl.setShortDescription("Mutation rate");
        propImpl.setPropertySet(PropertySets.MODEL);


        // validator & inplace editor
        final Validators validator = Validators.REQUIRE_VALID_NUMBER;

        propImpl.setValidator(validator);


        // inplace editor
        final ValidatingInplaceEditor editor = new ValidatingStringInplaceEditor();

        editor.addValidator(validator);
        propImpl.getCustomParamValues().put("inplaceEditor", editor);


        // key & default value
        propImpl.setKey(prefix + ".theta");
        propImpl.setValue(1.0);

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>
     *     {@code prefix.an = valid values are of the format f1^t1_f2^t2... where fi and ti are
     *     positive and represent the frequency domain, and the alleles on that frequency domain,
     *     respectively}
     *  </li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<String> of_Data_An(String prefix) {

        final Property<String> propImpl = Propertys.ofString();

        propImpl.setName("An");
        propImpl.setDisplayName("An");
        propImpl.setShortDescription("Infinite-Alleles Data");
        propImpl.setPropertySet(PropertySets.DATA);


        // validator & inplace editor
        propImpl.setPropEditorClass(AnPropertyEditor.class);

        final Validator<String> validator = Validators.regexp("(\\d+\\^\\d+_)*(\\d+\\^\\d+)",
                                                "It should be of the form f1^t1_f2^t2...", false);

        propImpl.setValidator(validator);


        // inplace editor
        final ValidatingInplaceEditor editor = new ValidatingStringInplaceEditor();

        editor.addValidator(validator);
        propImpl.getCustomParamValues().put("inplaceEditor", editor);


        // key & value
        propImpl.setKey(prefix + ".an");
        propImpl.setValue("1^3_2^1");

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code prefix.algorithm = "GUSFIELD" | "FOURGAMETES"}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property of_Algo_Phylogeny(final String prefix) {

        final CoalescentPropertyImpls.PhylogenyAlgorithmPropertyImpl propImpl =
            new CoalescentPropertyImpls.PhylogenyAlgorithmPropertyImpl();

        propImpl.setName("phylogeny-algorithm");
        propImpl.setDisplayName("phylogeny-algorithm");
        propImpl.setShortDescription("Phylogeny algorithm");
        propImpl.setPropertySet(PropertySets.ALGOS);


        // validator
        propImpl.setPropEditorClass(PhylogenyAlgorithmPropertyEditor.class);


        // key & value
        propImpl.setKey(prefix + ".algorithm");
        propImpl.setValue(PhylogenyAlgo.GUSFIELD);

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *     <li>{@code prefix.implCode = tab08:interval-mle}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<String> of_Estimators_K69(final String prefix) {

        final Property<String> propImpl = Propertys.ofString();

        propImpl.setName("k69-estimators");
        propImpl.setDisplayName("Estimators");
        propImpl.setShortDescription("Estimators for model K69");
        propImpl.setPropertySet(PropertySets.ALGOS);


        // property editor
        propImpl.setPropEditorClass(PropertyEditors.K69EstimatorPE.class);


        // key & value
        propImpl.setKey(prefix + ".implCode");
        propImpl.setValue("watterson");

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code prefix.exactProb = true | false}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<Boolean> of_Comp_K69_ExactProb(final String prefix) {

        final Property<Boolean> propImpl = Propertys.ofBoolean();

        propImpl.setName("compute-probability");
        propImpl.setDisplayName("compute probability?");
        propImpl.setShortDescription("Compute the exact probability");
        propImpl.setPropertySet(PropertySets.COMPS);


        // key & value
        propImpl.setKey(prefix + ".exactProb");
        propImpl.setValue(true);

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code prefix.configCounter = true | false}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<Boolean> of_Comp_K69_ConfigCount(final String prefix) {

        final Property<Boolean> propImpl = Propertys.ofBoolean();

        propImpl.setName("compute-config-count");
        propImpl.setDisplayName("compute config count?");
        propImpl.setShortDescription("Compute the total number of ancestral configurations");
        propImpl.setPropertySet(PropertySets.COMPS);


        // key & value
        propImpl.setKey(prefix + ".configCounter");
        propImpl.setValue(true);

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code prefix.genealogyCounter = true | false}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<Boolean> of_Comp_K69_GenealogyCount(final String prefix) {

        final Property<Boolean> propImpl = Propertys.ofBoolean();

        propImpl.setName("compute-genealogy-count");
        propImpl.setDisplayName("count genealogies?");
        propImpl.setShortDescription("Compute the total number of genealogies");
        propImpl.setPropertySet(PropertySets.COMPS);


        // key & value
        propImpl.setKey(prefix + ".genealogyCounter");
        propImpl.setValue(true);

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code prefix.configBuilder = true | false}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<Boolean> of_Comp_K69_ConfigBuilder(final String prefix) {

        final Property<Boolean> propImpl = Propertys.ofBoolean();

        propImpl.setName("compute-config-builder");
        propImpl.setDisplayName("build configs?");
        propImpl.setShortDescription("Build the ancestral configurations");
        propImpl.setPropertySet(PropertySets.COMPS);


        // key & value
        propImpl.setKey(prefix + ".configBuilder");
        propImpl.setValue(false);

        return propImpl;
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code prefix.genealogyBuilder = true | false}</li>
     * </ul>
     *
     * @return a new instance of the property
     * @param prefix
     */
    public static Property<Boolean> of_Comp_K69_GenealogyBuilder(final String prefix) {

        final Property<Boolean> propImpl = Propertys.ofBoolean();

        propImpl.setName("compute-genealogy-builder");
        propImpl.setDisplayName("build genealogies?");
        propImpl.setShortDescription("Build all genealogies");
        propImpl.setPropertySet(PropertySets.COMPS);


        // key & value
        propImpl.setKey(prefix + ".genealogyBuilder");
        propImpl.setValue(false);

        return propImpl;
    }

    public static BuilderProperty of_Builder_K69Data(String keyPrefix) {

        final BuilderProperty propImpl = Propertys.ofBuilder();

        propImpl.setName("K69Data-builders");
        propImpl.setDisplayName("K69 Data Sets");
        propImpl.setShortDescription("K69 Data Sets");
        propImpl.setPropertySet(PropertySets.DATA);


        // property editor
        propImpl.setPropEditorClass(PropertyEditors.K69DataBuilder_ExPE_IFactory.class);
        propImpl.setKeyPrefix(keyPrefix);

        return propImpl;
    }

    /**
     *
     */
    public static class Range_Theta {

        private Range_Theta() {}

        public static Property[] of_MinMaxIncrement(String prefix) {
            return new Property[] { min(prefix), max(prefix), increment(prefix) };
        }

        private static Property<Double> min(final String prefix) {

            final Property<Double> propImpl = Propertys.ofDouble();

            propImpl.setName("theta-min");
            propImpl.setDisplayName("Min theta value");
            propImpl.setShortDescription("Min theta value.");
            propImpl.setPropertySet(PropertySets.PARAMS);
            propImpl.setKey(prefix + ".min");
            propImpl.setValue(1.0);

            return propImpl;
        }

        private static Property<Double> max(final String prefix) {

            final Property<Double> propImpl = Propertys.ofDouble();

            propImpl.setName("theta-max");
            propImpl.setDisplayName("Max theta value");
            propImpl.setShortDescription("Max theta value.");
            propImpl.setPropertySet(PropertySets.PARAMS);
            propImpl.setKey(prefix + ".max");
            propImpl.setValue(5.0);

            return propImpl;
        }

        private static Property<Double> increment(final String prefix) {

            final Property<Double> propImpl = Propertys.ofDouble();

            propImpl.setName("theta-increment");
            propImpl.setDisplayName("Theta increment value");
            propImpl.setShortDescription("Theta increment value");
            propImpl.setPropertySet(PropertySets.PARAMS);
            propImpl.setKey(prefix + ".increment");
            propImpl.setValue(0.05);

            return propImpl;
        }
    }
}
